/*
 * Copyright (C) 2010 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.common.util;

import java.util.Calendar;
import java.util.Random;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

import com.mol.market.Constants;
import com.mol.market.Session;

/**
 * 通知栏推荐提醒，工具类
 * @author wufenglong
 * @date 2011-10-14
 * @since Version 0.8.1
 * */
public class AlarmManageUtils {
    
    /** 检查推送信息 */
    public static final int CODE_PUSH = 0;
    /** 检查更新信息 */
    public static final int CODE_CHECK_UPDATE = 1;
    /** 检查推送系统消息 */
    public static final int CODE_PUSH_MESSAGE = 2;
    /** 弹出通知 */
    public static final int CODE_ALARM = 3;
    /**新用户3天未登录*/
    public static final int CODE_NOLOGIN_3_DAY = 4;
    /**老用户7天未登录*/
    public static final int CODE_NOLOGIN_7_DAY = 5;
    

    private static AlarmManager getAlarmManager(Context c) {
        return (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
    }
    
    /**
     * 应用更新提醒
     * 规则: 距离上次打开机锋市场超过6天
     */
    public static void scheduleUpdateAlarm(Context c) {
        
        if (!Session.get(c).isNotificationRecommendApps()) {
            return;
        }
        final long nextTime = System.currentTimeMillis() + 518400000;
        Intent intent = new Intent(c, AppPushService.class);
        intent.putExtra(Constants.EXTRA_CATEGORY, CODE_CHECK_UPDATE);
        PendingIntent pendingIntent = PendingIntent.getService(c, 0, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = getAlarmManager(c);
        am.set(AlarmManager.RTC_WAKEUP, nextTime, pendingIntent);
    }
    
    /**
     * 循环发定时
     */
    public static void notifyPushService(Context c, boolean isForceNext) {
        
        if (!Session.get(c).isNotificationRecommendApps()) {
            return;
        }
        
        Intent intent = new Intent(c, AppPushService.class);
        intent.putExtra(Constants.EXTRA_CATEGORY, CODE_PUSH);
        PendingIntent pendingIntent = PendingIntent.getService(c, 0, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = getAlarmManager(c);
        long startTime = calculatePullTime(isForceNext);
        if (startTime < 0) {
            return;
        }
        am.set(AlarmManager.RTC_WAKEUP, startTime, pendingIntent);
    }
    
    /**
     * 循环发提醒
     */
    public static void notifyAlarmService(Context c, boolean isForceNext) {
        
        if (!Session.get(c).isNotificationRecommendApps()) {
            return;
        }
        
        Intent intent = new Intent(c, AppPushService.class);
        intent.putExtra(Constants.EXTRA_CATEGORY, CODE_ALARM);
        PendingIntent pendingIntent = PendingIntent.getService(c, 0, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = getAlarmManager(c);
        long startTime = calculateAlarmTime(isForceNext);
        if (startTime < 0) {
            return;
        }
        am.set(AlarmManager.RTC_WAKEUP, startTime, pendingIntent);
    }

    /** 
     * 暂停定时广播 
     */
    public static void cancelPushService(Context c) {
        AlarmManager am = getAlarmManager(c);
        Intent i = new Intent(c, AppPushService.class);
        PendingIntent pendingIntent = PendingIntent.getService(c, 0, i,
                PendingIntent.FLAG_CANCEL_CURRENT);
        am.cancel(pendingIntent);
    }
    
    /**
     * 在after时间之后推送信息，标识为Id
     * (不推荐使用此方法)
     * @param context
     * @param after          
     * @param Id 相同ID将覆盖
     * @param eventId 事件触发的ID，不同的ID所触发的事件不同。需要在AlarmManageUtils.class中注册
     * @event 触发事件在{@link #AppPushService}中添加
     */
    public static void notifyCallbackService(Context context,long after,int Id,int eventId){
        //提示不需要推送开关，这里将推送的开关删除 
        //by Chaos. 2012/9/4
        Intent intent = new Intent(context, AppPushService.class);
        intent.putExtra(Constants.EXTRA_CATEGORY, eventId);
        PendingIntent pendingIntent = PendingIntent.getService(context, Id, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = getAlarmManager(context);
        long startTime = System.currentTimeMillis() + after;
        am.set(AlarmManager.RTC_WAKEUP, startTime, pendingIntent);
    }
    /**
     * 在(rules时间 - pastTime)之后推送信息，标识为rulesId
     * @param context
     * @param rules
     * @param pastTime
     */
    public static void notifyCallbackService(Context context, PushRules rules, long pastTime){
        long after = rules.getAfterTime() - pastTime >= 0 ? rules.getAfterTime() : 0;
        notifyCallbackService(context, after, rules.getId(),rules.getEventId());
    }
    
    /*
     * 在rules时间之后推送信息，标识为rulesId
     */
    public static void notifyCallbackService(Context context, PushRules rules){
        notifyCallbackService(context,rules,0);
    }
    
    /**
     * 计算检查推送消息时间
     * 规则是24小时随机检查
     */
    public static long calculatePullTime(boolean isForceNext) {
        
        Calendar calendar = Calendar.getInstance();
        
        if (!isForceNext) {
            return calendar.getTimeInMillis();
        }
        
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        
        long time = calendar.getTimeInMillis() + new Random().nextInt(86400000);
//        Calendar temp = Calendar.getInstance();
//        temp.setTimeInMillis(time);
        return time;
    }
    
    /**
     * 计算提醒时间(重启手机状态)
     * 有效区间是 【每天中午12-14点】 以及 【每天下午20-23点】
     */
    public static long calculateAlarmTime(boolean isForceNext) {

        Calendar calendar = Calendar.getInstance();
        final int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
        final long now = System.currentTimeMillis();

        long nextTime = -1;
        if (currentHour < 10) {
            // 上午
            calendar.set(Calendar.HOUR_OF_DAY, 10);
            calendar.set(Calendar.MINUTE, 0);
            nextTime = calendar.getTimeInMillis() + new Random().nextInt(3600000);

        } else if (!isForceNext && currentHour < 14) {
            // 第一区间
            nextTime = now + new Random().nextInt(600000);

        } else if (currentHour < 20) {
            // 下午
            calendar.set(Calendar.HOUR_OF_DAY, 20);
            calendar.set(Calendar.MINUTE, 0);
            nextTime = calendar.getTimeInMillis() + new Random().nextInt(3600000);

        } else if (!isForceNext && currentHour < 23) {
            // 第二区间
            nextTime = now + new Random().nextInt(600000);

        } else {
            // 晚上
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 12);
            calendar.set(Calendar.MINUTE, 0);
            nextTime = calendar.getTimeInMillis() + new Random().nextInt(3600000);
        }
        
//        Calendar temp = Calendar.getInstance();
//        temp.setTimeInMillis(nextTime);
//        Utils.D("the next alarm time is >>>>>>>" + temp.getTime().toString());
        return nextTime;
    }
    
    /**
     * 推送规则
     * @author Chaos    
     *
     */
    public enum PushRules{
        /**新用户，3天未登录*/
        NOLOGIN_NEW_USER_3_DAY(4, CODE_NOLOGIN_3_DAY, 1000 * 60 * 60 * 24 * 3),
        /**老用户,7天未登录*/
        NOLOGIN_SILENCE_USER_7_DAY(4, CODE_NOLOGIN_7_DAY, 1000 * 60 * 60 * 24 * 7);
        
        private int id;
        private int eventId;
        private long afterTime;
        
        /**
         * 
         * @param id        如果id相同，则会覆盖之前设置的推送
         * @param eventId   如果eventId相同，则触发事件相同
         * @param afterTime 多长时间之后进行推送
         */
        private PushRules(int id,int eventId,long afterTime){
            this.id = id;
            this.eventId = eventId;
            this.afterTime = afterTime;
        }

        public long getAfterTime() {
            return afterTime;
        }

        public int getId(){
            return id;
        }
        
        public int getEventId(){
            return eventId;
        }

    }
}
